package com.ikingtech.platform.service.system.dept.service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.iking.framework.sdk.authorization.api.AuthorizationDepartmentApi;
import com.iking.framework.sdk.authorization.model.AuthorizationUserDepartment;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.enums.system.department.DeptTypeEnum;
import com.ikingtech.framework.sdk.enums.system.role.DataScopeTypeEnum;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.platform.service.system.dept.entity.DepartmentDO;
import com.ikingtech.platform.service.system.dept.service.repository.DeptRepository;
import lombok.RequiredArgsConstructor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author tie yan
 */
@RequiredArgsConstructor
public class AuthorizationDepartmentService implements AuthorizationDepartmentApi {

    private final DeptRepository repo;

    @Override
    public List<String> loadFullPathAll() {
        return this.repo.listObjs(Wrappers.<DepartmentDO>lambdaQuery()
                .select(DepartmentDO::getFullPath)
                .eq(DepartmentDO::getTenantCode, Me.tenantCode()));
    }

    @Override
    public List<String> loadFullPath(List<String> ids) {
        if (Tools.Coll.isBlank(ids)) {
            return new ArrayList<>();
        }
        return this.repo.listObjs(Wrappers.<DepartmentDO>lambdaQuery()
                .select(DepartmentDO::getFullPath)
                .in(DepartmentDO::getId, ids)
                .eq(DepartmentDO::getTenantCode, Me.tenantCode()));
    }

    @Override
    public List<String> loadFullPath(List<AuthorizationUserDepartment> departments,
                                     DataScopeTypeEnum dataScopeType) {
        List<String> unityIds = Tools.Coll.convertList(departments, department -> DeptTypeEnum.UNITY.equals(department.getDeptType()), AuthorizationUserDepartment::getDeptId);
        if (DataScopeTypeEnum.SECTION.equals(dataScopeType)) {
            List<String> deptFullPaths = Tools.Coll.convertList(departments, AuthorizationUserDepartment::getDeptFullPath);
            if (Tools.Coll.isNotBlank(unityIds)) {
                deptFullPaths.addAll(this.repo.listObjs(Wrappers.<DepartmentDO>lambdaQuery()
                        .select(DepartmentDO::getId)
                        .in(DepartmentDO::getParentId, unityIds)
                        .eq(DepartmentDO::getType, DeptTypeEnum.SECTION.name())
                        .eq(DepartmentDO::getTenantCode, Me.tenantCode())));
            }
            return deptFullPaths;
        }
        if (DataScopeTypeEnum.UNITY.equals(dataScopeType)) {
            List<String> sectionIds = Tools.Coll.convertList(departments, department -> DeptTypeEnum.SECTION.equals(department.getDeptType()), AuthorizationUserDepartment::getDeptId);
            if (Tools.Coll.isNotBlank(sectionIds)) {
                unityIds.addAll(this.repo.findUnityIds(sectionIds));
            }
            return Tools.Coll.isBlank(unityIds) ?
                    Collections.emptyList() :
                    this.repo.listObjs(Wrappers.<DepartmentDO>lambdaQuery()
                            .select(DepartmentDO::getId)
                            .in(DepartmentDO::getId, unityIds)
                            .or(wrapper ->
                                    wrapper
                                            .in(DepartmentDO::getParentId, unityIds)
                                            .eq(DepartmentDO::getType, DeptTypeEnum.SECTION.name()))
                            .eq(DepartmentDO::getTenantCode, Me.tenantCode()));
        }
        return Collections.emptyList();
    }

    @Override
    public List<String> loadSubFullPath(List<AuthorizationUserDepartment> departments,
                                        DataScopeTypeEnum dataScopeType) {
        if (DataScopeTypeEnum.SECTION_WITH_CHILD.equals(dataScopeType)) {
            return Tools.Coll.isBlank(departments) ?
                    Collections.emptyList() :
                    this.repo.listObjs(Wrappers.<DepartmentDO>lambdaQuery()
                            .select(DepartmentDO::getFullPath)
                            .and(wrapper -> Tools.Coll.convertList(departments, AuthorizationUserDepartment::getDeptFullPath).forEach(fullPath -> wrapper.or().likeRight(DepartmentDO::getFullPath, fullPath)))
                            .eq(DepartmentDO::getTenantCode, Me.tenantCode()));
        }
        if (DataScopeTypeEnum.UNITY_WITH_CHILD.equals(dataScopeType)) {
            List<String> sectionIds = Tools.Coll.convertList(departments, department -> DeptTypeEnum.SECTION.equals(department.getDeptType()), AuthorizationUserDepartment::getDeptId);
            List<String> unityFullPaths = Tools.Coll.convertList(departments, department -> DeptTypeEnum.UNITY.equals(department.getDeptType()), AuthorizationUserDepartment::getDeptFullPath);
            if (Tools.Coll.isNotBlank(sectionIds)) {
                unityFullPaths.addAll(Tools.Coll.convertList(this.repo.findUnitiesById(sectionIds), DepartmentDO::getFullPath));
            }
            return Tools.Coll.isBlank(unityFullPaths) ?
                    Collections.emptyList() :
                    this.repo.listObjs(Wrappers.<DepartmentDO>lambdaQuery()
                            .select(DepartmentDO::getFullPath)
                            .and(wrapper -> unityFullPaths.forEach(fullPath -> wrapper.or().likeRight(DepartmentDO::getFullPath, fullPath)))
                            .eq(DepartmentDO::getTenantCode, Me.tenantCode()));
        }
        return Collections.emptyList();
    }
}
